﻿using System;
using System.Collections;
using System.Configuration.Install;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;

namespace SuiHan.Commons.WindowsService {
    public class ServiceHelper {
        /// <summary>
        /// 服务是否存在
        /// </summary>
        /// <param name="serviceName"></param>
        public static ServiceController GetService(string serviceName) {
            ServiceController[] services = ServiceController.GetServices();
            return services.FirstOrDefault(s => s.ServiceName == serviceName);
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="serviceName"></param>
        public static void StartService(string serviceName) {
            ServiceController service = GetService(serviceName);
            if (service != null) {
                if (service.Status != ServiceControllerStatus.Running &&
                    service.Status != ServiceControllerStatus.StartPending) {
                    service.Start();
                    for (int i = 0; i < 60; i++) {
                        service.Refresh();
                        Thread.Sleep(1000);
                        if (service.Status == ServiceControllerStatus.Running) {
                            break;
                        }

                        if (i == 59) {
                            throw new Exception("Start Service Error：" + serviceName);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 获取服务状态
        /// </summary>
        /// <param name="serviceName"></param>
        public static ServiceControllerStatus GetServiceStatus(string serviceName) {
            ServiceController service = new(serviceName);
            return service.Status;
        }

        /// <summary>
        /// 配置服务
        /// </summary>
        /// <param name="installer">ServiceInstaller</param>
        /// <param name="installOrUninstall">true: 安装, false: 卸载</param>
        public static void ConfigService(ServiceInstaller installer, bool installOrUninstall) {
            TransactedInstaller ti = new() {
                Context = new InstallContext {
                    Parameters = {
                        ["assemblypath"] = $"\"{Assembly.GetEntryAssembly()!.Location}\" -service"
                    }
                }
            };
            ti.Installers.Add(new ServiceProcessInstaller {
                Account = ServiceAccount.LocalSystem,
            });
            ti.Installers.Add(installer);

            if (installOrUninstall) {
                ti.Install(new Hashtable());
            } else {
                ti.Uninstall(null);
            }
        }
    }
}
